#include "stdafx.h" 
#include "cCamera.h"
#include "cPlayer.h"
#include "cObject.h"

cCamera* gpCamera;

cCamera::cCamera(void)
{
	mTarget = D3DXVECTOR3( PLAYER_X, PLAYER_Y+40.f, PLAYER_Z-5.f);
	mTargetObj = NULL;
	
	mPos = D3DXVECTOR3( 0.f, 0.f, 0.f );
	mUp = D3DXVECTOR3(0.0f, 1.0f, 0.0f);

	mfDist = 10.f ;
	mYrot = -0.014601808f;
	mXrot = 4.2353973f;
	
	gpCamera = this;

}
//////////////////////////////////////////////////////////////////////////
cCamera::~cCamera(void)
{
}
//////////////////////////////////////////////////////////////////////////
D3DXMATRIX cCamera::getViewTM()
{
	D3DXMATRIX ViewTM;
	
	if ( mTargetObj )
	{
		D3DXVECTOR3 dir = mPos - mTarget;
		D3DXVec3Normalize(&dir, &dir);

		static D3DXVECTOR3 oldRot(0.f, 0.f, 0.f);
		D3DXVECTOR3 rot = mTargetObj->mRotation;
		if ( oldRot != rot)
		{
			D3DXMATRIX m;
			D3DXMatrixRotationY(&m, rot.y - oldRot.y);
			D3DXVec3TransformCoord(&dir, &dir, &m);
			oldRot = rot;
		}

		mTarget = mTargetObj->mPosition;
		mPos = (dir*mfDist) + mTarget;
	}
	else{
		D3DXMATRIX m;
		D3DXMatrixRotationYawPitchRoll(&m, mYrot, mXrot, 0.f);
		D3DXVECTOR3 dir(m._31, m._32, m._33);

		mPos = (dir*mfDist) + mTarget;
	}

	D3DXMatrixLookAtLH(&ViewTM, &mPos, &mTarget, &mUp);

	return ViewTM;
}
//////////////////////////////////////////////////////////////////////////
D3DXMATRIX cCamera::getBillboardTM()
{
	D3DXMATRIX mat = getViewTM();
	mat._41 = 0.f; mat._42 = 0.f; mat._43 = 0.f;
	D3DXMatrixInverse(&mat, NULL, &mat);
	return mat;
}
//////////////////////////////////////////////////////////////////////////
D3DXMATRIX cCamera::getBillboardTM_Y( D3DXVECTOR3& Lookat )
{
	D3DXMATRIX mat;
	// Set up a rotation matrix to orient the billboard towards the camera.
	D3DXVECTOR3 vDir = Lookat - mPos;
	if( vDir.x > 0.0f )
		D3DXMatrixRotationY( &mat, -atanf(vDir.z/vDir.x)+D3DX_PI/2 );
	else
		D3DXMatrixRotationY( &mat, -atanf(vDir.z/vDir.x)-D3DX_PI/2 ); 

	return mat;
}
//////////////////////////////////////////////////////////////////////////
void cCamera::strafe(float units)
{
	D3DXVECTOR3 right ;
	D3DXVECTOR3 dir = mTarget - mPos ;
	dir.y = 0.f;
	D3DXVec3Normalize(&dir, &dir);
	D3DXVec3Cross(&right, &mUp, &dir);

	mPos += right * units;
	mTarget += right * units;
}
//////////////////////////////////////////////////////////////////////////
void cCamera::fly(float units)
{
	mPos.y += units;
}
//////////////////////////////////////////////////////////////////////////
void cCamera::walk(float units)
{
	//    D3DXVECTOR3 dir = mTarget - mPos ;
	//    //dir.y = 0.f;
	//    D3DXVec3Normalize(&dir, &dir);
	// 
	//    mPos += dir * units;
	//    mTarget += dir * units;
	mfDist += units;
}
//////////////////////////////////////////////////////////////////////////
void cCamera::pitch(float degree)
{
	D3DXMATRIX m;
	D3DXVECTOR3 right ;
	D3DXVECTOR3 dir = mTarget - mPos ;
	dir.y = 0.f;
	D3DXVec3Normalize(&dir, &dir);
	D3DXVec3Cross(&right, &mUp, &dir);

	D3DXMatrixRotationAxis(&m, &right, degree );
	D3DXVECTOR3 target_vec = mTarget - mPos;
	D3DXVec3TransformCoord(&target_vec, &target_vec, &m );

	mTarget = mPos + target_vec;
}
//////////////////////////////////////////////////////////////////////////
void cCamera::pitch3(float degree)
{
	//D3DXVECTOR3 oldPos = mPos;
	//D3DXVECTOR3 oldTarget = mTarget;

	//D3DXMATRIX m;
	//D3DXVECTOR3 right ;
	//D3DXVECTOR3 dir = mTarget - mPos ;
	//dir.y = 0.f;
	//D3DXVec3Normalize(&dir, &dir);
	//D3DXVec3Cross(&right, &mUp, &dir);

	//D3DXVECTOR3 target_vec = mTarget - mPos;

	//D3DXMatrixRotationAxis(&m, &right, degree );
	//D3DXVec3TransformCoord(&target_vec, &target_vec, &m );
	//D3DXVec3TransformCoord(&mPos, &mPos, &m);

	//mTarget = mPos + target_vec;
	//reCalc( oldPos, oldTarget );
	mXrot += degree;
}
//////////////////////////////////////////////////////////////////////////
void cCamera::yaw(float degree)
{
	D3DXMATRIX m;
	D3DXMatrixRotationY(&m, degree);
	D3DXVECTOR3 target_vec = mTarget- mPos;
	D3DXVec3TransformCoord(&target_vec, &target_vec, &m );

	mTarget = mPos + target_vec;
}
//////////////////////////////////////////////////////////////////////////
void cCamera::yaw3(float degree)
{
	//    D3DXMATRIX m;
	//    D3DXMatrixRotationY(&m, degree);
	//    D3DXVECTOR3 target_vec = mTarget - mPos;
	//    D3DXVec3TransformCoord(&target_vec, &target_vec, &m );
	//    D3DXVec3TransformCoord(&mPos, &mPos, &m);
	//    mTarget = mPos + target_vec;
	mYrot += degree;
}
//////////////////////////////////////////////////////////////////////////
void cCamera::roll(float degree)
{
	D3DXMATRIX m;
	D3DXMatrixRotationZ(&m, degree);
	D3DXVECTOR3 target_vec = mTarget - mPos;
	D3DXVec3TransformCoord(&target_vec, &target_vec, &m );

	mTarget = mPos + target_vec;
}
//////////////////////////////////////////////////////////////////////////
void cCamera::reCalc(D3DXVECTOR3 oldPos, D3DXVECTOR3 oldTarget)
{
	D3DXVECTOR3 target_vec = mPos - mTarget;
	D3DXVec3Normalize(&target_vec, &target_vec);
	if( D3DXVec3Dot(&target_vec, &mUp) > 0.95f
		|| mPos.y < 1.f )
	{
		mPos = oldPos ;
		mTarget = oldTarget;
	}
}
//////////////////////////////////////////////////////////////////////////
void cCamera::SetTargetObj(cObject* obj)
{
	mTargetObj = obj ;
}
//////////////////////////////////////////////////////////////////////////
void cCamera::ProcessKeyInput()
{
	if (gDInput->keyDown(DIK_W))
	{
		D3DXVECTOR3 dir = mTarget - mPos;
		dir.y = 0.5f;
		D3DXVec3Normalize(&dir, &dir);

		mPos		+= dir*0.9f ;
		mTarget	+= dir*0.9f ;
	}

	if (gDInput->keyDown(DIK_S))
	{
		D3DXVECTOR3 dir = mTarget - mPos;
		dir.y = 0.f;
		D3DXVec3Normalize(&dir, &dir);

		mPos		-= dir*0.5f ;
		mTarget-= dir*0.5f ;
	}

	if (gDInput->keyDown(DIK_D))
	{
		D3DXVECTOR3 right;
		D3DXVECTOR3 up(0.f, 1.f, 0.f);
		D3DXVECTOR3 dir = mTarget - mPos;
		dir.y = 0.f;
		D3DXVec3Normalize(&dir, &dir);
		D3DXVec3Cross(&right, &up, &dir);
		mPos		+= right*0.5f ;
		mTarget	+= right*0.5f ;
	}

	if (gDInput->keyDown(DIK_A))
	{
		D3DXVECTOR3 right;
		D3DXVECTOR3 up(0.f, 1.f, 0.f);
		D3DXVECTOR3 dir = mTarget - mPos;
		dir.y = 0.f;
		D3DXVec3Normalize(&dir, &dir);
		D3DXVec3Cross(&right, &up, &dir);
		mPos		-= right*0.5f ;
		mTarget	-= right*0.5f ;
	}

	if (gDInput->keyDown(DIK_Q))
	{
		D3DXMATRIX m;
		D3DXMatrixRotationY(&m, 0.07f);
		D3DXVECTOR3 target_vec = mTarget - mPos;
		D3DXVec3TransformCoord( &target_vec, &target_vec, &m );
		mTarget = mPos + target_vec; 
	}

	if (gDInput->keyDown(DIK_E))
	{
		D3DXMATRIX m;
		D3DXMatrixRotationY(&m, -0.07f);
		D3DXVECTOR3 target_vec = mTarget- mPos;
		D3DXVec3TransformCoord( &target_vec, &target_vec, &m );
		mTarget = mPos + target_vec;
	}

	if (gDInput->keyDown(DIK_PGUP))
	{
		D3DXMATRIX m;
		D3DXMatrixRotationX(&m, 0.007f);
		D3DXVECTOR3 target_vec = mTarget - mPos;
		D3DXVec3TransformCoord(&target_vec, &target_vec, &m);
		mTarget = mPos - target_vec;
		if (mTarget.y<D3DX_PI*90/180)
		{
			mTarget -=D3DXVECTOR3(0.f, 2.f, 0.f); 
		}
	}

	if (gDInput->keyDown(DIK_PGDN))
	{
		D3DXMATRIX m;
		D3DXMatrixRotationX(&m, -0.007f);
		D3DXVECTOR3 target_vec = mTarget + mPos;
		D3DXVec3TransformCoord(&target_vec, &target_vec, &m);
		mTarget = mPos + target_vec;
	}
}